package demo.security;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

/**
 * spring security 安全性配置
 */
@Configuration
@EnableGlobalMethodSecurity(
        securedEnabled = true,
        // jsr250Enabled = true,
        prePostEnabled = true)
public class SecurityConfig {
    // 密码加密工具
    private final PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf(csrf -> csrf.disable());
        http.authorizeHttpRequests(authorize -> {
                            try {
                                authorize
                                        .requestMatchers("/security/admin").hasAnyRole("ADMIN") // 系统管理员才能访问
                                        .requestMatchers("/security/**").authenticated() // /security 必须登陆才能访问
                                        // 放行资源目录
                                        .requestMatchers("/static/**", "/resources/**").permitAll()
                                        // 其余的都需要权限校验
//                                .anyRequest().authenticated()
                                        .anyRequest().permitAll()
                                // 防跨站请求伪造
                                ;
                            } catch (Exception e) {
                                throw new RuntimeException(e);
                            }
                        }
                )
                .formLogin(formCfg -> {
                    formCfg//.loginPage("/login")
                            .defaultSuccessUrl("/security/login-success") // 登陆成功后跳转到
                            .permitAll();
                }).logout(logoutCfg -> {
                    logoutCfg.invalidateHttpSession(true)
                            .clearAuthentication(true)
                            .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                            .logoutSuccessUrl("/")
                            .permitAll();
                }).rememberMe(rmb -> {
                    rmb.tokenValiditySeconds(1209600)
                            .rememberMeCookieName("remember-me");
                });
        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        // 创建两个内部账户，实际环境中一般会把用户信息保存到数据库中，实现接口 UserDetailsService
        User.UserBuilder builder = User.builder();
        // 普通用户 user，初始密码：123456
        UserDetails user = builder
                .username("user")
                .password(passwordEncoder.encode("123456"))
                .roles("USER")
                .build();
        // 管理员用户 admin
        UserDetails admin = builder
                .username("admin")
                .password(passwordEncoder.encode("123456"))
                .roles("ADMIN")
                .build();
        // 使用 InMemoryUserDetailsManager, 加入用户
        return new InMemoryUserDetailsManager(user, admin);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return passwordEncoder;
    }
}
